/* A simple server in the internet domain using TCP
   The port number is passed as an argument
   This version runs forever, forking off a separate
   process for each connection
   gcc server2.c -lsocket
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#include <iostream>
#include <sstream>
#include <cstdlib>
#include <strings.h>
#include <cstring>
#include <string>

#include "libraries/Operaciones.h"

using namespace std;

void dostuff(int); /* function prototype */

void error(string msg)
{
    cout<<msg;
    exit(1);
}

int main(int argc, char *argv[])
{
     int sockfd, newsockfd, portno, clilen, pid;
     struct sockaddr_in serv_addr, cli_addr;

     if (argc < 2) {
         fprintf(stderr,"ERROR, no port provided\n");
         exit(1);
     }
     sockfd = socket(AF_INET, SOCK_STREAM, 0);
     if (sockfd < 0)
        error("ERROR opening socket\n");
     bzero((char *) &serv_addr, sizeof(serv_addr));
     portno = atoi(argv[1]);
     serv_addr.sin_family = AF_INET;
     serv_addr.sin_addr.s_addr = INADDR_ANY;
     serv_addr.sin_port = htons(portno);
     if (bind(sockfd, (struct sockaddr *) &serv_addr,
              sizeof(serv_addr)) < 0)
              error("ERROR on binding\n");
     listen(sockfd,5); //Escuchamos en el socket. 5 es el número de peticiones máximas en cola
     clilen = sizeof(cli_addr);
     while (1) {
         newsockfd = accept(sockfd,
               (struct sockaddr *) &cli_addr,(socklen_t*) &clilen);
         if (newsockfd < 0)
             error("ERROR on accept\n");
         pid = fork();
         if (pid < 0)
             error("ERROR on fork\n");
         if (pid == 0)  {
             close(sockfd);
             //dostuff(newsockfd);


    int n=0, Sum1=0, Sum2=0, i=0, a=0, b=0;
    char buffer[256], buffer_sol[256], op[5], s1[125], s2[125];
    double result;
    enum oper{Sm, Rs, Dv, Mp, Ex,Rz };
      
    bzero(buffer,256);
    n = read(newsockfd,buffer,255);
	bzero(op,5);

    if (n < 0) error("ERROR reading from socket (server) \n");


    do
    {
        op[i]=buffer[i];
        i++;
    }while (buffer[i]!='.');

    //op = atoi(op);

    i++;

    do
    {
        s1[a]=buffer[i];
        a++;
        i++;
    }while (buffer[i]!='.');

    Sum1 = atoi(s1);
	//cout << "Sum1: " << Sum1 << endl; Perfect

    i++;

    do
    {
        s2[b]=buffer[i];
        b++;
        i++;
    }while (buffer[i]!='\0');

    Sum2 = atoi(s2);
	//cout << "Sum2: " << Sum2 << endl; Perfect
	
    switch (atoi(op))
    {
    case Sm:
        result=suma(Sum1,Sum2);
        break;

    case Rs:
        result=resta(Sum1,Sum2);
        break;

    case Dv:
        result=divi(Sum1,Sum2);
        break;

    case Mp:
        result=mult(Sum1,Sum2);
        break;

    case Ex:
        result=exp(Sum1,Sum2);
        break;

    case Rz:
        result=raiz(Sum1);
        break;

    default:

        cout << "Operación no reconocida\n" << endl;
        break;

    }

	stringstream result_buffer;
   	result_buffer << result;
   	string rB = result_buffer.str();

	//cout << "Result: " << result << endl; //Perfect
	//cout << "Buffer_sol: " << rB.c_str() << endl;//Perfect

    n = write(newsockfd,rB.c_str(),rB.size());
	//cout << n << endl; //Perfect.
    if (n < 0) error("ERROR writing to socket (server)\n");

             exit(0);
         }
         else close(newsockfd);
     } 
     return 0;
}


